#include "CHtmlCounter.h"

CHtmlCounter::CHtmlCounter()
{
	classtype = HTML;
	language_name = "HTML";
	casesensitive = false;

	file_extension.push_back(".*htm");

	BlockCommentStart.push_back("<!--");
	BlockCommentEnd.push_back("-->");

	exec_name_list.push_back("ADDRESS");
	exec_name_list.push_back("APPLET");
	exec_name_list.push_back("AREA");
	exec_name_list.push_back("A");
	exec_name_list.push_back("BASE");
	exec_name_list.push_back("BASEFONT");
	exec_name_list.push_back("BIG");
	exec_name_list.push_back("BLOCKQUOTE");
	exec_name_list.push_back("BODY");
	exec_name_list.push_back("BR");
	exec_name_list.push_back("B");
	exec_name_list.push_back("CAPTION");
	exec_name_list.push_back("CENTER");
	exec_name_list.push_back("CITE");
	exec_name_list.push_back("CODE");
	exec_name_list.push_back("DD");
	exec_name_list.push_back("DFN");
	exec_name_list.push_back("DIR");
	exec_name_list.push_back("DIV");
	exec_name_list.push_back("DL");
	exec_name_list.push_back("DT");
	exec_name_list.push_back("EM");
	exec_name_list.push_back("FONT");
	exec_name_list.push_back("FORM");
	exec_name_list.push_back("H1");
	exec_name_list.push_back("H2");
	exec_name_list.push_back("H3");
	exec_name_list.push_back("H4");
	exec_name_list.push_back("H5");
	exec_name_list.push_back("H6");
	exec_name_list.push_back("HEAD");
	exec_name_list.push_back("HR");
	exec_name_list.push_back("HTML");
	exec_name_list.push_back("IMG");
	exec_name_list.push_back("INPUT");
	exec_name_list.push_back("ISINDEX");
	exec_name_list.push_back("I");
	exec_name_list.push_back("jsp");
	exec_name_list.push_back("KBD");
	exec_name_list.push_back("LINK");
	exec_name_list.push_back("LI");
	exec_name_list.push_back("MAP");
	exec_name_list.push_back("MENU");
	exec_name_list.push_back("META");
	exec_name_list.push_back("OL");
	exec_name_list.push_back("OPTION");
	exec_name_list.push_back("PARAM");
	exec_name_list.push_back("PRE");
	exec_name_list.push_back("P");
	exec_name_list.push_back("SAMP");
	exec_name_list.push_back("SCRIPT");
	exec_name_list.push_back("SELECT");
	exec_name_list.push_back("SMALL");
	exec_name_list.push_back("SPAN");
	exec_name_list.push_back("STRIKE");
	exec_name_list.push_back("STRONG");
	exec_name_list.push_back("STYLE");
	exec_name_list.push_back("SUB");
	exec_name_list.push_back("SUP");
	exec_name_list.push_back("TABLE");
	exec_name_list.push_back("TD");
	exec_name_list.push_back("TEXTAREA");
	exec_name_list.push_back("TH");
	exec_name_list.push_back("TITLE");
	exec_name_list.push_back("TR");
	exec_name_list.push_back("TT");
	exec_name_list.push_back("UL");
	exec_name_list.push_back("U");
	exec_name_list.push_back("VAR");
}

int CHtmlCounter::CountDirectiveSLOC(filemap* fmap, results* result, filemap* fmapBak)
{	
	result->directive_lines[PHY] = 0;
	result->directive_lines[LOG] = 0;
	return 0;
}

int CHtmlCounter::LanguageSpecificProcess(filemap* fmap, results* result, filemap* fmapBak)
{
	bool blank_flag	= false;
	bool comment	= false;
	bool intag		= false;
	int cnt = 0;	//for CUtil::CountTally use
	size_t comPos = INVALID_POSITION; //Mod042909AS
	size_t p;
	filemap::iterator fit;
	string l;
	string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";

	string strLSLOC;
	string strLSLOCBak;
	int l_paren_cnt = 0;
	char prev_char = 0;
	int phys_exec_lines = 0;
	int phys_data_lines = 0;
	int temp_lines = 0;

	for (fit = fmap->begin(); fit!= fmap->end(); fit++)
	{
		l = fit->line;
		if (comment==true)
		{
			p = l.find("-->");
			if (p!=string::npos)
			{
				if (p>0)
					l.replace(0,p,"");

				comment = false;
			}
			else continue;
		}

		comPos=l.find("<!--");
		if (comPos==string::npos)
		{
			comment = false;
			comPos = INVALID_POSITION; //Mod042909AS
		}
		else
		{
			comment = true;
			if (!(comPos+4 >= l.size()))
			{
				p = l.find("-->",comPos+4);
				if( p!=string::npos)
				{
					if (p-comPos-4 > 0)
					{l.replace(comPos+4,p-comPos-4,"");}
					comment = false;
				} 
				else
				{
					if (comPos+4!=l.size()-1)
						l.replace(comPos+4,l.size()-comPos-3,"");
				}
			}
		}

		if (CUtil::CheckBlank(l))
		{
			blank_flag = true;// the line is either blank/whole line comment/compiler directive
			continue;
		}
		else
		{
			blank_flag = false;// should be processed by this func
		}

		result->exec_lines[PHY]++;

		if (intag==true)
		{
			p = l.find("<");
			if (p!=string::npos)
			{
				if (p>0)
					l.replace(0,p,"");

				intag = false;
			}
			else continue;
		}

		comPos=l.find(">");
		if (comPos==string::npos)
		{
			intag = false;
			comPos = INVALID_POSITION; //Mod042909AS
		}
		else
		{
			intag = true;
			if (!(comPos+1 >= l.size()))
			{

				p = l.find("<",comPos+1);
				if (p!=string::npos)
				{
					if (p-comPos-1 > 0)
						l.replace(comPos+1,p-comPos-1,"");
					intag = false;
				}
				else
				{
					if (comPos!=l.size()-1)
						l.replace(comPos+1,l.size()-comPos,"");
				}
			}
		}
		cnt = 0;
		CountHtmlTally(l,exec_name_list, cnt, 1, exclude, "", "", &exec_name_count, result->duplicate, false);

		result->data_lines[PHY]=0;
		result->data_lines[LOG]=0;

		LSLOC(result,l ,l, strLSLOC, strLSLOCBak, l_paren_cnt,prev_char ,temp_lines, phys_exec_lines, phys_data_lines);

		result->exec_lines[PHY] += phys_exec_lines;		/* Update physical SLOC lines*/
		phys_exec_lines = 0;

		result->data_lines[PHY] += phys_data_lines;
		phys_data_lines = 0;

	} //for
	return 0;

} //func

// Method: LSLOC(...)
// Description: determine and extract logical SLOC to place in the result variable
//              using addSLOC function. Each time the addSLOC function is called,
//              a new logical SLOC is added. This function assumes that the directive
//              is handled before it is called.
// -----------------------------------------
// Revision  Date     Author  Modification
// Rev-1     4/19/09   VN      Created the method signature (frame).
//								Note:the parameters list must be added
void CHtmlCounter::LSLOC(results* result, string line, string lineBak, string &strLSLOC, string &strLSLOCBak, int &paren_cnt,
						 char &prev_char,int &temp_lines, int &phys_exec_lines, int &phys_data_lines)
{
	size_t start = 0; //starting index of the working string
	size_t i = 0, strSize;
	string tmp;
	bool trunc_flag = false;

	while (i < line.length())
	{
		if (line[i] == '<')
		{
			if (line[i] == '<' && line[i+1] == '/')
			{
				i++;
				continue;
			}
			if (line[i] == '<' && line[i+1] == '?')
			{
				i++;
				continue;
			}
			if (line[i] == '<' && line[i+1] == '!')
			{
				i++;
				continue;
			}

			strSize = CUtil::TruncateLine(i - start, strLSLOC.length(), result->lsloc_truncate, trunc_flag);
			if (strSize > 0)
			{
				strLSLOC += line.substr(start, strSize);
				strLSLOCBak += lineBak.substr(start, strSize);
			}
			result->addSLOC(strLSLOCBak, trunc_flag);
			result->exec_lines[LOG]++;
			temp_lines++;
			strLSLOC = "";
			strLSLOCBak = "";
			start = i + 1;
		}
		else if (line[i] == '>')
		{
			// Also, <> is also skipped, empty block is not counted
			if (prev_char == '/' || prev_char == '<')
			{
				start = i + 1; 
			}
		}
		i++;
	}

	tmp = CUtil::TrimString(line.substr(start, i - start));
	strSize = CUtil::TruncateLine(tmp.length(), strLSLOC.length(), result->lsloc_truncate, trunc_flag);
	if (strSize > 0)
	{
		strLSLOC += tmp.substr(0, strSize);
		tmp = CUtil::TrimString(lineBak.substr(start, i - start));
		strLSLOCBak += tmp.substr(0, strSize);
	}
	phys_data_lines = temp_lines;
}

void CHtmlCounter::CountHtmlTally(string base, StringVector& container, int &count, int mode, string exclude,
								  string include1, string include2, IntPairVector* counter_container, bool dup, bool casesensitive)
{
	base = " "+base+" ";
	string::size_type idx;
	string base1 = "";
	string temp = "";
	StringVector::iterator vit;
	IntPairVector::iterator cit;
	int single_count = 0;

	if (counter_container)
	{
		cit = counter_container->begin();
	}	

	if (casesensitive==false)
	{
		base1 = CUtil::to_lower(base);
		for(vit=container.begin(); vit != container.end(); vit++)
			(*vit) = CUtil::to_lower((*vit));
	}
	else
		base1=base;	
	
	if (mode == 1)
	{	// exclude mode
		for (vit=container.begin(); vit != container.end(); vit++)
		{
			temp = "<" + *vit;
			//temp=*vit;
		
			idx = base1.find(temp);
			while (idx != string::npos)
			{
				if ((exclude.find(base1[idx+(temp.size())] ) == string::npos) &&
					(exclude.find(base1[idx-1]) == string::npos))
				{
					count++;
					single_count++;
				}
				idx = base1.find(temp, idx+(temp.size()));
			}
			if (counter_container)
			{
				if (dup)
					(*cit).second += single_count;
				else
					(*cit).first += single_count;
				single_count = 0;
				cit++;
			
			}
		}
	}
}

CHtmlPhpCounter::CHtmlPhpCounter()
{
	classtype = HTML_PHP;
	language_name = "HTML/PHP";

	file_extension.clear();
	file_extension.push_back(".*/htmphp");
}

CHtmlJspCounter::CHtmlJspCounter()
{
	classtype = HTML_JSP;
	language_name = "HTML/JSP";

	file_extension.clear();
	file_extension.push_back(".*/htmjsp");
}

CHtmlAspCounter::CHtmlAspCounter()
{
	classtype = HTML_ASP;
	language_name = "HTML/ASP";

	file_extension.clear();
	file_extension.push_back(".*/htmasp");
}
